//
//  ACIAPManager.m
//  ACFramework
//
//  Created by caoyq on 2018/6/11.
//  Updated by caoyq on 2018/6/20.
//

#import "ACIAPManager.h"
#import "ACProgressHUD.h"

static NSString *const sandBoxUrl = @"https://sandbox.itunes.apple.com/verifyReceipt";
static NSString *const itunesUrl = @"https://buy.itunes.apple.com/verifyReceipt";

@interface ACIAPManager()<SKPaymentTransactionObserver, SKProductsRequestDelegate>

@property (nonatomic, weak) id<ACIAPManagerDelegate>delegate;
/** 购买的商品的id */
@property (nonatomic, strong) NSString *productId;
/** 沙盒环境或真实环境. 沙盒环境用于测试支付*/
@property (nonatomic, assign) BOOL isSandBoxEnvironment;

@end

@implementation ACIAPManager

#pragma mark - Init

+ (instancetype)manager
{
    static ACIAPManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    
    return instance;
}

#pragma mark - public

- (void)addObserverAndDelegate: (id<ACIAPManagerDelegate>)delegate
{
    self.delegate = delegate;
    
    if (![SKPaymentQueue canMakePayments]) {
        [self createFailDelegateWitherrorInfo:ACIAPErrorCode0Description errorCode:ACIAPErrorCode0];
        return;
    }
    
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}

- (void)removeObserver
{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

- (void)startPaymentWithID: (NSString *)productId isSandBoxEnvironment: (BOOL)isSandBoxEnvironment
{
    [self checkUnFinishedTransaction];
    
    if (!productId) {
        [self createFailDelegateWitherrorInfo:ACIAPErrorCode1Description errorCode:ACIAPErrorCode1];
        return;
    }
    self.isSandBoxEnvironment = isSandBoxEnvironment;
    self.productId = productId;
    [self requestProductData];
}

#pragma mark - 支付入口

///请求 App Store 商品数据.返回数据后，直接走的代理方法： productsRequest: didReceiveResponse:
- (void)requestProductData
{
    //set数组添加几个元素，后面从App Store返回的商品列表数组就拥有几个元素
    NSString *productId = self.productId;
    NSSet *set = [NSSet setWithArray:@[productId]];
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
    request.delegate = self;
    [request start];
    [ACProgressHUD showHUD];
}

#pragma mark - SKProductsRequestDelegate

//代理方法运行完 走监督方法 updatedTransactions
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    //查询到App Store可用的商品列表
    NSArray *productList = response.products;
//    NSLog(@"无效产品Product ID:%@",response.invalidProductIdentifiers);
    
    if (productList.count == 0) {
        [self createFailDelegateWitherrorInfo:ACIAPErrorCode2Description errorCode:ACIAPErrorCode2];
    }
    
    //从后台获取的商品列表 从中找到我们需要的商品
    SKProduct *requestProduct = nil;
    for (SKProduct *pro in productList) {
//        NSLog(@"product info");
//        NSLog(@"SKProduct 描述信息%@", [pro description]);
//        NSLog(@"产品标题 %@" , pro.localizedTitle);
//        NSLog(@"产品描述信息: %@" , pro.localizedDescription);
//        NSLog(@"价格: %@" , pro.price);
//        NSLog(@"Product id: %@" , pro.productIdentifier);
        
        if ([pro.productIdentifier isEqualToString:self.productId]) {
            requestProduct = pro;
            break;
        }
    }
    if (!requestProduct) {
        [self createFailDelegateWitherrorInfo:ACIAPErrorCode3Description errorCode:ACIAPErrorCode3];
    }
    
    ///寻找到正确商品后 发送购买请求
    SKPayment *payment = [SKPayment paymentWithProduct:requestProduct];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

#pragma mark - SKPaymentTransactionObserver

//购买事件的监听
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
{
    for(SKPaymentTransaction *tran in transactions){
        
        switch (tran.transactionState) {
            case SKPaymentTransactionStatePurchased: //交易完成
                [self completedTransaction:tran];
                break;
            case SKPaymentTransactionStateRestored:  //已经购买过该商品
                [self restoredTransaction:tran];
                break;
            case SKPaymentTransactionStateFailed: //交易失败
                [self failedTransaction:tran];
                break;
            case SKPaymentTransactionStatePurchasing: //商品添加进列表
                break;
            default:
                break;
        }
    }
}

#pragma mark - 交易结果

///交易完成
- (void)completedTransaction: (SKPaymentTransaction *)transaction
{
    //开始 App Store 票据的校验
    NSString *iapReceipt = [self iapReceipt];
    if (!iapReceipt) {
        [self createFailDelegateWitherrorInfo:ACIAPErrorCode6Description errorCode:ACIAPErrorCode6];
        return;
    }

    NSString *url = _isSandBoxEnvironment ? sandBoxUrl : itunesUrl;

    [self verifyIapReceipt:iapReceipt url:url success:^{
        if (self.delegate && [self.delegate respondsToSelector:@selector(ac_iapManagerPaymentDidSuccess:)]) {
            [self.delegate ac_iapManagerPaymentDidSuccess:self];
        }
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
        [ACProgressHUD hideHUD];
    } failure:^(NSError *error) {
        if (self.delegate && [self.delegate respondsToSelector:@selector(ac_iapManager:paymentDidFailWithError:)]) {
            [self.delegate ac_iapManager:self paymentDidFailWithError:error];
        }
//        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
        [ACProgressHUD hideHUD];
    }];
}

///已经购买
- (void)restoredTransaction: (SKPaymentTransaction *)transaction
{
    [ACProgressHUD hideHUD];
    
    // 对于已购商品，处理恢复购买的逻辑
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

///交易失败
- (void)failedTransaction: (SKPaymentTransaction *)transaction
{
    [ACProgressHUD hideHUD];
    
    if(transaction.error.code != SKErrorPaymentCancelled) {
        [self createFailDelegateWitherrorInfo:ACIAPErrorCode4Description errorCode:ACIAPErrorCode4];
    } else {
        [self createFailDelegateWitherrorInfo:ACIAPErrorCode5Description errorCode:ACIAPErrorCode5];
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

#pragma mark - 票据验证

///获取交易的票据
- (NSString *)iapReceipt
{
    /*
     BASE64 常用的编码方案，通常用于数据传输，以及加密算法的基础算法，传输过程中能够保证数据传输的稳定性
     */
    NSString *receiptString = nil;
    NSURL *rereceiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    if ([[NSFileManager defaultManager] fileExistsAtPath:[rereceiptURL path]]) {
        NSData *receiptData = [NSData dataWithContentsOfURL:rereceiptURL];
        receiptString = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    }
    return receiptString;
}

///对票据进行验证（苹果官方接口）
- (void)verifyIapReceipt: (NSString *)iapReceipa
                     url: (NSString *)url
                 success:(void (^)(void))successBlock
                 failure:(void (^)(NSError *error))failureBlock
{
    NSString *sendString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", iapReceipa];
    
    NSData *postData = [NSData dataWithBytes:[sendString UTF8String] length:[sendString length]];
    
    NSMutableURLRequest *connectionRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
    
    [connectionRequest setHTTPMethod:@"POST"];
    [connectionRequest setTimeoutInterval:50.0];
    [connectionRequest setCachePolicy:NSURLRequestUseProtocolCachePolicy];
    [connectionRequest setHTTPBody:postData];
    
    // [NSURLSession sharedSession] dataTaskWithRequest: completionHandler: 方法调用之后没有结果，于是不采用block回调。
    
    NSError *error = nil;
    NSData *responseData=[NSURLConnection sendSynchronousRequest:connectionRequest returningResponse:nil error:&error];
    if (error) {
        //票据校验失败
        if (failureBlock) {
            failureBlock(error);
        }
        return;
    }
    
    NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
    
    NSInteger statusCode = [responseJSON[@"status"] integerValue];
    //不是0 的状态码对用不同的错误，按照状态码核对
    if (statusCode == 0) {
        //成功
        if (successBlock) {
            successBlock();
        }
    }else {
        NSError *error = [[NSError alloc] initWithDomain:NSCocoaErrorDomain code:statusCode userInfo:@{NSLocalizedDescriptionKey: ACIAPErrorCode7Description}];
        if (failureBlock) {
            failureBlock(error);
        }
    }
}

#pragma mark - private

///核实是否能存在未完成的订单
-(void)checkUnFinishedTransaction
{
    NSArray* transactions = [SKPaymentQueue defaultQueue].transactions;
    if (transactions.count > 0) {
        //检测是否有未完成的交易
        SKPaymentTransaction* transaction = [transactions firstObject];
        if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
            [self completedTransaction:transaction];
            return;
        }
    }
}

///创建一个基本的错误信息 并用delegate返回
- (void)createFailDelegateWitherrorInfo: (NSString *)errorInfo errorCode: (NSInteger)errorCode
{
    if (self.delegate && [self.delegate respondsToSelector:@selector(ac_iapManager:paymentDidFailWithError:)]) {
        NSDictionary *errorDic = @{NSLocalizedDescriptionKey: errorInfo};
        NSError *error = [[NSError alloc] initWithDomain:NSCocoaErrorDomain code:errorCode userInfo:errorDic];
        [self.delegate ac_iapManager:self paymentDidFailWithError:error];
    }
}

@end
